package com.tenoz.display3d
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.utils.Dictionary;
	
	public class SimplePlane extends Sprite
	{
		private var bmd:BitmapData;
		
		private var p:Array;
		private var mesh:Array;
		private var _width:Number;
		private var _height:Number;
		private var _segX:int;
		private var _segY:int;
		private var uvMatrices:Dictionary = new Dictionary();
		
		public function get tl():Point
		{
			var pnt:Point = p[0][0];
			return pnt;
		}
		public function get tr():Point
		{
			var pnt:Point = p[0][_segX];
			return pnt;
		}
		public function get bl():Point
		{
			var pnt:Point = p[_segY][0];
			return pnt;
		}
		public function get br():Point
		{
			var pnt:Point = p[_segY][_segX];
			return pnt;
		}
		
		public function set tl(value:Point):void
		{
			p[0][0] = value;
		}
		public function set tr(value:Point):void
		{
			p[0][_segX] = value;
		}
		public function set bl(value:Point):void
		{
			p[_segY][0] = value;
		}
		public function set br(value:Point):void
		{
			p[_segY][_segX] = value;
		}
		
		public var bmp:Bitmap;
		public function SimplePlane(_bmd:BitmapData, w:Number=0, h:Number=0, segX:int=1, segY:int=1)
		{
			this.bmd = _bmd;
			this._width = (w==0)? this.bmd.width : w;
			this._height = (h==0)? this.bmd.height : h;
			this._segX = (segX<=0)? 1 : segX;
			this._segY = (segY<=0)? 1 : segY;
			
			createMesh();
			
//			bmp = new Bitmap(bmd);
//			addChild(bmp);
//			
//			this.x = 250;
//			this.y = 250;
//			this.rotationX = -45;
		}
		
		private function createMesh():void
		{
			var i:int=0;
			var j:int=0;
			p = [];
			for(i=0; i<=_segY; i++)
			{
				p[i] = [];
				for(j=0; j<=_segX; j++)
				{
					p[i][j] = new Point(_width*(j/_segX), _height*(i/_segY));
				}
			}
			var tri:Triangle;
			mesh = [];
			for(i=0; i<_segY; i++)
			{
				for(j=0; j<_segX; j++)
				{
					tri = new Triangle(p[i][j], p[i][j+1], p[i+1][j]);
					mesh.push(tri);
					transformUVRT(tri);
					tri = new Triangle(p[i][j+1], p[i+1][j+1], p[i+1][j]);
					mesh.push(tri);
					transformUVRT(tri);
				}
			}
		}
		
		private var x0:Number;
		private var y0:Number;
		private var x1:Number;
		private var y1:Number;
		private var x2:Number;
		private var y2:Number;
		private var x3:Number;
		private var y3:Number;
		
		public function draw():void
		{
			var _triMatrix:Matrix = new Matrix();
			var g:Graphics = this.graphics;
			g.clear();
			
			var _triMap:Matrix;
			var tri:Triangle;
			
			updateGrid();
			
			var i:int=0;
			var j:int=0;
			var leng:int= mesh.length;
			for(i=0; i<leng; i++)
			{
				tri = mesh[i];
				_triMap = this.uvMatrices[tri].clone();
//				for(j=0; j<_segX; j++)
//				{
					x0 = tri.p0.x;
					y0 = tri.p0.y;
					x1 = tri.p1.x;
					y1 = tri.p1.y;
					x2 = tri.p2.x;
					y2 = tri.p2.y;
//					x3 = p[i+1][j].x;
//					y3 = p[i+1][j].y;
//					
					_triMatrix.a = (x1 - x0);///(_width/_segX);
					_triMatrix.b = (y1 - y0);///(_height/_segY);
					_triMatrix.c = (x2 - x0);///(_width/_segX);
					_triMatrix.d = (y2 - y0);///(_height/_segY);
					_triMatrix.tx = x0;
					_triMatrix.ty = y0;
					
					_triMap.concat(_triMatrix);
					
					g.lineStyle(1,0xFF00FF);
					g.beginBitmapFill(bmd, _triMap, false, true);
					g.moveTo(x0, y0);
					g.lineTo(x1, y1);
					g.lineTo(x2, y2);
					g.lineTo(x0, y0);
//					
//					_triMatrix.a = (x2 - x3)/(_width/_segX);
//					_triMatrix.b = (y2 - y3)/(_height/_segY);
//					_triMatrix.c = (x2 - x1)/(_width/_segX);
//					_triMatrix.d = (y2 - y1)/(_height/_segY);
//					_triMatrix.tx = x3 + x1 - x2;
//					_triMatrix.ty = y1 + y3 - y2;
//					
//					g.beginBitmapFill(bmd, _triMatrix, false, true);
//					g.moveTo(x1, y1);
//					g.lineTo(x2, y2);
//					g.lineTo(x3, y3);
//					g.lineTo(x1, y1);
//				}
			}
		}
		
		private function updateGrid():void
		{
			var i:int=0;
			var j:int=0;
			
			for(i=1; i<_segY; i++)
			{
				p[i][0].x = p[0][0].x+(p[_segY][0].x - p[0][0].x)*(i/_segY);
				p[i][0].y = p[0][0].y+(p[_segY][0].y - p[0][0].y)*(i/_segY);
			}
			for(i=1; i<_segY; i++)
			{
				p[i][_segX].x = p[0][_segX].x+(p[_segY][_segX].x - p[0][_segX].x)*(i/_segY);
				p[i][_segX].y = p[0][_segX].y+(p[_segY][_segX].y - p[0][_segX].y)*(i/_segY);
			}
			
			for(i=1; i<_segX; i++)
			{
				p[0][i].x = p[0][0].x+(p[0][_segX].x - p[0][0].x)*(i/_segX);
				p[0][i].y = p[0][0].y+(p[0][_segX].y - p[0][0].y)*(i/_segX);
			}
			for(i=1; i<_segX; i++)
			{
				p[_segY][i].x = p[_segY][0].x+(p[_segY][_segX].x - p[_segY][0].x)*(i/_segY);
				p[_segY][i].y = p[_segY][0].y+(p[_segY][_segX].y - p[_segY][0].y)*(i/_segY);
			}
			
			for(i=1; i<_segY; i++)
			{
				for(j=1; j<_segX; j++)
				{
					p[i][j].x = p[i][0].x+(p[i][_segY].x - p[i][0].x)*(j/_segX);
					p[i][j].y = p[0][j].y+(p[_segX][j].y - p[0][j].y)*(i/_segY);
				}
			}
		}
		
		public function transformUVRT(tri:Triangle):void
		{
			//var uv :Array  = face3D.uv;
			
			var w  :Number = _width;
			var h  :Number = _height;
			var u0 :Number = w * tri.p0.x;
			var v0 :Number = h * ( 1 - tri.p0.y );
			var u1 :Number = w * tri.p1.x;
			var v1 :Number = h * ( 1 - tri.p1.y);
			var u2 :Number = w * tri.p2.x;
			var v2 :Number = h * ( 1 - tri.p2.y );
			
			// Fix perpendicular projections
			if( (u0 == u1 && v0 == v1) || (u0 == u2 && v0 == v2) )
			{
				u0 -= (u0 > 0.05)? 0.05 : -0.05;
				v0 -= (v0 > 0.07)? 0.07 : -0.07;
			}
			
			if( u2 == u1 && v2 == v1 )
			{
				u2 -= (u2 > 0.05)? 0.04 : -0.04;
				v2 -= (v2 > 0.06)? 0.06 : -0.06;
			}
			
			// Precalculate matrix & correct for mip mapping
			var at :Number = ( u1 - u0 );
			var bt :Number = ( v1 - v0 );
			var ct :Number = ( u2 - u0 );
			var dt :Number = ( v2 - v0 );
			
			var m :Matrix = new Matrix( at, bt, ct, dt, u0, v0 );
			m.invert();
			
			uvMatrices[tri] = m.clone();
		}
	}
}
import flash.geom.Point;

class Triangle
{
	public var p0:Point;
	public var p1:Point;
	public var p2:Point;
	public function Triangle(p0:Point, p1:Point, p2:Point)
	{
		this.p0 = p0;
		this.p1 = p1;
		this.p2 = p2;
	}
}